package com.ht.demo.service.system;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 封装线程Callable的实现类
 * 继承此类可节省线程实现的代码，推荐使用
 * @Author hdengxian
 * @Date 2022/12/27 9:09
 */

public abstract class BaseThreadManager<T> implements Callable {
    Logger logger = LoggerFactory.getLogger(BaseThreadManager.class);
    //执行的线程池中的线程数
    private static int threadSerialNum = 0;
    //lock锁
    private static Lock lock = new ReentrantLock();
    //线程池
    private ExecutorService executorService = null;
    //返回值实例
    Future future = null;
    private CountDownLatch countDownLatch = null;

    public BaseThreadManager() {
        executorService = Executors.newCachedThreadPool();
    }

    @Override
    public Object call() throws Exception {
        T t = null;
        try {
            //需要子类实现
            t = execute();

            lock.lock();
            threadSerialNum += 1;
            lock.unlock();
            logger.info("第【{}】个线程执行完成", threadSerialNum);
        }finally {
            if (countDownLatch != null) {
                countDownLatch.countDown();
            }
        }
        return t;
    }

    /**
     * 需要子类实现的抽象方法
     * @auther hdengxian
     * @Date 2022/12/27 9:44
     */
    public abstract T execute() throws Exception;

    public void submit(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
        future = executorService.submit(this);
        executorService.shutdown();
    }

    public void submit(ExecutorService executorService, CountDownLatch countDownLatch) {
        this.executorService = executorService;
        this.countDownLatch = countDownLatch;
        future = executorService.submit(this);
        executorService.shutdown();
    }

    public void submit() {
        future = executorService.submit(this);
        executorService.shutdown();
    }

    public void submit(ExecutorService executorService) {
        this.executorService = executorService;
        future = executorService.submit(this);
        executorService.shutdown();
    }

    public T getData() {
        T t = null;
        try {
            t = (T) future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return t;
    }

    public T getData(long timeout, TimeUnit unit) {
        T t = null;
        try {
            t = (T) future.get(timeout, unit);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return t;
    }



}
